<template>
  <div>
    <el-row class="full-height" style="margin-left: 10px; margin-right: 10px;" :gutter="15">
      <el-form ref="elForm" size="medium" label-width="100px">
        <el-col :span="4">
          <el-row class="col">1</el-row>
        </el-col>
        <el-col :span="15">
          <el-row class="col">
            <div class="canvas-top">
              <div>
                <a-button class="canvas-button" type="primary" ghost @click="viewportLeftObject">左侧</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportCenterObject">居中</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportRightObject">右侧</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportTopObject">顶部</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportBottomObject">底部</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportCenterObjectV">垂直</a-button>
                <a-button class="canvas-button" type="primary" ghost @click="viewportCenterObjectH">水平</a-button>
              </div>
              <div>
                <a-button type="primary">确定</a-button>
                <a-button type="primary" style="margin: auto 10px;" @click="removeObj">删除</a-button>
                <a-button type="primary" @click="batch">批量操作</a-button>
              </div>
            </div>
            <div ref="canvasContainer" class="canvas-container">
              <canvas id="canvas" ref="canvas" />
            </div>
          </el-row>
        </el-col>
        <el-col :span="5">
          <el-row class="col canvas-right">
            <div class="right">
              <div v-show="isShows">
                <h2>名称:</h2>
                <div>{{ msg }}</div>
                <h1>位置和尺寸</h1>
                <div>X:{{ positionX }}</div>
                <div>Y:{{ positionY }}</div>
                <div>角度:</div>
                <div>W:</div>
                <div>H:</div>
              </div>
              <div v-show="isShow">
                <el-tree
                  :data="data"
                  :props="defaultProps"
                  @node-click="handleNodeClick"
                >
                  <template v-slot="{ node, data }">
                    <span v-html="renderLabel(data)" />
                  </template>
                </el-tree>

                <el-button
                  style="margin-left: 25%; margin-top: 20px"
                  @click="add"
                >确认</el-button>
              </div>
            </div>
            <a-menu
              v-show="showMenu"
              ref="contextMenu"
              class="custom-context-menu"
              style="display: none"
              @click="handleMenuClick"
            >
              <a-menu-item-group>
                <a-sub-menu title="添加">
                  <a-menu-item key="menu1">设备/点位</a-menu-item>
                  <a-menu-item key="menu2">文本框</a-menu-item>
                </a-sub-menu>
                <a-menu-item key="menu3">复制</a-menu-item>
                <a-menu-item key="menu4">粘贴</a-menu-item>
                <a-menu-item key="menu5">剪切</a-menu-item>
                <a-menu-item key="menu6">编辑文本</a-menu-item>
                <a-menu-item key="menu7">设置背景图</a-menu-item>
              </a-menu-item-group>
            </a-menu>
          </el-row>
        </el-col>

      </el-form>
    </el-row>
  </div>
</template>
<script>
import { fabric } from 'fabric'
export default {
  data() {
    return {
      canvas: null, // 画布对象
      positionX: 0, // 右键点击位置的横坐标
      positionY: 0, // 右键点击位置的纵坐标
      imgX: 0, // 右键点击位置的横坐标
      imgY: 0, // 右键点击位置的纵坐标
      imgurl: '', // 选中图片路径
      msg: '', // 点位信息
      width: '',
      group: null, // 组对象
      selectedObjects: [], // 左键选中对象数组
      isShow: false,
      isShows: false,
      showMenu: false,
      data: [
        {
          label: '设备定义A',
          imageUrl:
            'https://p2.ssl.qhimgs1.com/sdr/400__/t011714670591d793e8.jpg',
          children: [
            {
              imageUrl:
                'https://p0.ssl.qhimgs1.com/sdr/400__/t01655d74f994199afe.jpg',
              label: '温度'
            }
          ]
        },
        {
          label: '设备定义B',
          imageUrl:
            'https://p0.ssl.qhimgs1.com/sdr/400__/t049b21844b0ad74eb4.jpg',
          children: [
            {
              imageUrl:
                'https://p0.ssl.qhimgs1.com/sdr/400__/t0115cea72354f25a30.jpg',
              label: '风速'
            },
            {
              imageUrl:
                'https://p0.ssl.qhimgs1.com/sdr/400__/t01b3a5a18109dea24a.jpg',
              label: '温度'
            }
          ]
        },
        {
          label: '设备定义C',
          imageUrl:
            'https://p1.ssl.qhimgs1.com/sdr/400__/t0161e57b58736f7ef1.jpg',
          children: [
            {
              imageUrl:
                'https://p0.ssl.qhimgs1.com/sdr/400__/t0198d2cd3bb2772f96.jpg',
              label: '湿度'
            },
            {
              imageUrl:
                'https://p0.ssl.qhimgs1.com/sdr/400__/t0464a6f767310c9414.jpg',
              label: '温度'
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    }
  },

  mounted() {
    // 初始化画布
    this.canvas = new fabric.Canvas('canvas', {
      backgroundColor: '#ccc', // 画布背景颜色
      fireRightClick: true // 启用右键
    })
    // 监听鼠标右键在画布的位置
    this.canvas.on('mouse:down', (event) => {
      console.log(event.e.button)
      if (event.e.button === 2) {
        const pointer = this.canvas.getPointer(event.e)
        this.positionX = pointer.x
        this.positionY = pointer.y
      }
    })
    this.setCanvasSize()
    window.addEventListener('resize', this.setCanvasSize) // 设置画布大小
    document.addEventListener('contextmenu', this.showCustomContextMenu) // 右键菜单显示的位置
    document.addEventListener('click', this.hideCustomContextMenu) // 点击菜单外部区域时隐藏菜单
    // 阻止默认右键菜单事件
    this.canvas.upperCanvasEl.addEventListener('contextmenu', (e) => {
      e.preventDefault() // 禁止默认右键菜单
      // 获取 a-menu 组件实例
      const contextMenu = this.$refs.contextMenu
      // 设置自定义菜单的位置
      contextMenu.$el.style.display = 'block'
      contextMenu.$el.style.left = `${e.pageX}px`
      contextMenu.$el.style.top = `${e.pageY}px`
    })
    this.$nextTick(() => {
      document.addEventListener('contextmenu', this.showCustomContextMenu)
    })
    this.addMultiSelectAndDeleteFeature(this.canvas)
  },
  beforeDestroy() {
    document.removeEventListener('contextmenu', this.showCustomContextMenu)
  },
  methods: {
    // 设置画布大小
    setCanvasSize() {
      const canvasContainer = this.$refs.canvasContainer
      console.log(this.$refs.canvasContainer.clientHeight)
      const width = canvasContainer.clientWidth
      this.width = canvasContainer.clientWidth
      const height = this.$refs.canvasContainer.clientHeight
      console.log(width, height)
      this.canvas.setDimensions({ width, height })
    },
    // 右键菜单点击
    handleMenuClick(command) {
      console.log(command)
      // 根据点击的菜单项执行相应的操作
      if (command.key === 'menu1') {
        console.log('设备/点位')
        this.isShow = true
      } else if (command.key === 'menu2') {
        console.log('文本框')
      } else if (command.key === 'menu3') {
        console.log('复制')
        const activeObject = this.canvas.getActiveObject()
        if (activeObject && activeObject.type === 'image') {
          const imageURL = activeObject.getSrc()
          this.copiedObject = {
            type: 'image',
            src: imageURL
          }
        }
      } else if (command.key === 'menu4') {
        console.log('粘贴')
        if (this.copiedObject && this.copiedObject.type === 'image') {
          const img = new Image()
          img.src = this.copiedObject.src
          img.onload = () => {
            const fabricImage = new fabric.Image(img)
            fabricImage.set({
              left: this.positionX, // 使用右键点击位置的横坐标
              top: this.positionY // 使用右键点击位置的纵坐标
            })
            this.canvas.add(fabricImage)
            this.canvas.setActiveObject(fabricImage)
            this.canvas.requestRenderAll()
          }
        }
      } else if (command.key === 'menu5') {
        console.log('剪切')
        const activeObject = this.canvas.getActiveObject()
        if (activeObject) {
          this.copiedObject = activeObject
          this.canvas.remove(activeObject)
          this.canvas.discardActiveObject()
          this.canvas.renderAll()
        }
      }
      // 最后记得隐藏自定义菜单
      this.hideAllCustomMenus()
    },
    updateXY(x, y) {
      // 更新xy轴的数值
      console.log('X坐标:' + x + ',Y坐标:' + y)
      this.positionX = x
      this.positionY = y
    },
    //  创建点位方法
    addPT() {
      // 创建图片对象
      fabric.Image.fromURL(this.imgurl, (img) => {
        console.log(this.width)
        img.set({
          left: this.positionX, // 使用右键点击位置的横坐标
          top: this.positionY, // 使用右键点击位置的纵坐标
          width: 100, // 图片宽度
          height: 100 // 图片高度
        })
        console.log(this.positionX + this.width)
        img.selectable = true // 设置图片可以被选择
        // 创建一个矩形对象
        var rect = new fabric.Rect({
          left: this.positionX, // 使用右键点击位置的横坐标
          top: this.positionY + 120, // 使用右键点击位置的纵坐标
          fill: 'red', // 矩形填充颜色
          width: 100, // 矩形宽度
          height: 30 // 矩形高度
        })
        var text = new fabric.Text(this.msg, {
          left: rect.left + 10, // 文本左上角 x 坐标
          top: rect.top + 10, // 文本左上角 y 坐标
          fontSize: 20, // 字体大小
          fontFamily: 'Arial', // 字体类型
          fill: 'white' // 文本颜色
        })
        // 创建一个组,包含图片/矩形和文本
        this.group = new fabric.Group([img, rect, text], {
          left: img.left,
          top: img.top + 100 // 将文本放在图片下方
        })
        // 添加点击事件监听器
        // 添加点击和拖动事件监听器
        this.group.on('mousedown', (options) => {
          console.log('组被点击了')
          this.isShow = false
          this.isShows = true
          var grp = this.group
          var pointer = this.canvas.getPointer(options.e)
          var offsetX = pointer.x - grp.left
          var offsetY = pointer.y - grp.top

          // 获取当前的xy轴坐标
          var currentX = grp.left
          var currentY = grp.top
          this.positionX = currentX
          this.positionY = currentY
          // 添加拖动事件监听器
          this.canvas.on('mouse:move', (options) => {
            this.isShow = false
            this.isShows = true
            if (grp !== undefined) {
              var pointer = this.canvas.getPointer(options.e)
              grp.set({
                left: pointer.x - offsetX,
                top: pointer.y - offsetY
              })
              this.canvas.renderAll()
              // 实时更新xy轴的数值
              this.updateXY(grp.left, grp.top)
            }
          })

          this.canvas.on('mouse:up', () => {
            this.canvas.off('mouse:move')
            this.canvas.off('mouse:up')
            // 在鼠标释放后移除事件监听器,结束拖动状态
          })
        })
        // 将组添加到画布
        this.canvas.add(this.group)
      })
    },

    // 点击隐藏上一个菜单
    hideAllCustomMenus() {
      // 隐藏所有自定义右键菜单
      const menus = document.querySelectorAll('.custom-context-menu')
      menus.forEach((menu) => {
        menu.style.display = 'none'
      })
    },

    // 右键菜单显示的位置
    showCustomContextMenu(e) {
      const canvasContainer = this.$refs.canvasContainer
      // 判断右键事件是否发生在画布内部
      if (canvasContainer.contains(e.target)) {
        console.log(this.positionX + '和' + this.positionY)
        e.preventDefault()
        const contextMenu = this.$refs.contextMenu
        // const canvasRect = this.$refs.canvas.getBoundingClientRect()
        // const menuWidth = contextMenu.$el.offsetWidth
        // const menuHeight = contextMenu.$el.offsetHeight
        // // this.positionX = e.clientX - canvasRect.left - this.width
        // // this.positionY = e.clientY - canvasRect.top
        // // 防止菜单超出画布边界
        // const maxX = canvasRect.width - menuWidth - this.width - 20
        // const maxY = canvasRect.height - menuHeight
        const left = Math.min(this.positionX) - this.width
        const top = Math.min(this.positionY)
        contextMenu.$el.style.display = 'block'
        contextMenu.$el.style.left = `${left}px`
        contextMenu.$el.style.top = `${top}px`
      }
    },
    // 点击菜单外部区域时隐藏菜单
    hideCustomContextMenu(e) {
      const contextMenu = this.$refs.contextMenu
      if (!contextMenu.$el.contains(e.target)) {
        // 点击菜单外部区域时隐藏菜单
        this.showMenu = false
        console.log(this.showMenu)
      }
    },
    // 树插入图片
    renderLabel(data) {
      // 在这个方法中根据data的内容来生成label,可以包含图片和文本
      return `<span><img src="${data.imageUrl}" style="width: 50px; height: 50px; margin-right: 20px; ">${data.label}</span>`
    },
    // 树点击
    handleNodeClick(data) {
      console.log(data.label)
      this.msg = data.label
      this.imgurl = data.imageUrl
    },
    // 确定
    add() {
      this.addPT()
    },
    // 水平垂直居中
    viewportCenterObject() {
      this.canvas.viewportCenterObject(this.group)
    },
    // 水平居中
    viewportCenterObjectH() {
      this.canvas.viewportCenterObjectH(this.group)
    },
    // 垂直居中
    viewportCenterObjectV() {
      this.canvas.viewportCenterObjectV(this.group)
    },
    // 顶部
    viewportTopObject() {
      this.group.set({ top: 0 }) // 设置对象的顶部偏移量
      this.canvas.renderAll() // 重新渲染画布
    },
    // 底部
    viewportBottomObject() {
      const viewportHeight = this.canvas.getHeight() // 获取视口(画布)宽度
      console.log(viewportHeight)
      this.group.set({ top: viewportHeight - 150 }) // 设置对象的底部偏移量
      this.canvas.renderAll() // 重新渲染画布
    },
    // 左测
    viewportLeftObject() {
      this.group.set({ left: 0 }) // 设置对象的左侧偏移量
      this.canvas.renderAll() // 重新渲染画布
    },
    // 右侧
    viewportRightObject() {
      const viewportRightObject = this.canvas.getWidth() // 获取视口(画布)宽度
      console.log(viewportRightObject)
      this.group.set({ left: viewportRightObject - 100 }) // 设置对象的左侧偏移量
      this.canvas.renderAll() // 重新渲染画布
    },
    // 删除单个
    removeObj() {
      var activeObject = this.canvas.getActiveObject()
      console.log(activeObject, 5555555)
      this.canvas.remove(activeObject)
      this.canvas.renderAll() // 重新渲染画布
    },
    // 选中多个对象
    addMultiSelectAndDeleteFeature(canvas) {
      var isMouseDown = false // 标记鼠标左键是否按下
      var startPoint, endPoint // 记录选框的起始点和终点

      // 监听鼠标按下事件
      canvas.on('mouse:down', function(options) {
        console.log(options.e.button)
        if (options.e.button === 0) { // 检测鼠标左键
          startPoint = canvas.getPointer(options.e)
          isMouseDown = true
        }
      })

      // 监听鼠标移动事件
      canvas.on('mouse:move', function(options) {
        if (!isMouseDown) return

        endPoint = canvas.getPointer(options.e)

        // 绘制选框
        var left = Math.min(startPoint.x, endPoint.x)
        var top = Math.min(startPoint.y, endPoint.y)
        var width = Math.abs(endPoint.x - startPoint.x)
        var height = Math.abs(endPoint.y - startPoint.y)

        canvas.selection = false
        canvas.clearContext(canvas.contextTop)
        canvas.contextTop.strokeStyle = 'blue'
        canvas.contextTop.lineWidth = 1
        canvas.contextTop.strokeRect(left, top, width, height)
      })

      // 监听鼠标抬起事件
      canvas.on('mouse:up', function(options) {
        if (options.e.button === 0 && isMouseDown) { // 检测鼠标左键抬起
          isMouseDown = false

          // 计算选框的包围盒
          var boundingBox = new fabric.Rect({
            left: Math.min(startPoint.x, endPoint.x),
            top: Math.min(startPoint.y, endPoint.y),
            width: Math.abs(endPoint.x - startPoint.x),
            height: Math.abs(endPoint.y - startPoint.y),
            fill: 'rgba(0,0,0,0)',
            selectable: false,
            evented: false
          })

          var selectedObjects = canvas.getObjects().filter(function(obj) {
            return obj.intersectsWithObject(boundingBox) && obj !== boundingBox
          })
          console.log(selectedObjects, '数组')
          // 清除选框
          canvas.clearContext(canvas.contextTop)

          // // 删除选中的对象
          // for (var i = 0; i < selectedObjects.length; i++) {
          //   canvas.remove(selectedObjects[i])
          // }

          canvas.renderAll()
        }
      })
    }
  }
}

</script>
<style>

.col {
  border: 1px solid #000;
  height: 93vh; /* 将高度设置为视口高度 */
  margin-top: 5px;
  /* padding: 20px; 可根据实际需要调整 */
  box-sizing: border-box; /* 让 padding 不影响元素的实际高度 */
}

.custom-context-menu {
  z-index: 1000; /* 设置一个足够大的 z-index 值 */
  position: absolute; /* 添加定位样式 */
}
.ant-menu-submenu-title {
  position: relative;
}

.ant-menu-horizontal .ant-menu-submenu {
  position: absolute;
  top: 0;
  right: 100%; /* 调整这里的数值来控制右侧弹出的位置 */
  min-width: 180px; /* 设置子菜单的宽度 */
}
.right {
  width: 100%;
  height: 100%;
  border: 1px solid #000;
  border-radius: 15px;
  padding-top: 20px;
}
.right div {
  font-size: 20px;
  color: black;
}
.el-tree-node__content {
  /* 修改节点的高度 */
  height: 80px;
}
.canvas-container {
  position: relative;
  width: 100%;
  height: 95%; /* 设置父容器的默认高度 */
}
.canvas-top{
  position: relative;
  width: 100%;
  height: 5%; /* 设置父容器的默认高度 */
  display: flex;
  align-items: center;
  justify-content: space-between;
 padding-left: 20px;
 padding-right: 20px;
}
.canvas-button{
  margin-right: 20px;
}

.canvas-right{
  border: 0;
}
#canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

</style>
